package com.rainwen.shiro.service;


import com.rainwen.shiro.entity.SysResource;
import com.rainwen.shiro.enums.ResourceEnum;
import com.rainwen.shiro.mapper.SysResourceMapper;
import com.rainwen.shiro.mapper.SysRoleResourceMapper;
import com.rainwen.shiro.vo.ResourcePermissionVO;
import com.rainwen.shiro.vo.ResourceVO;
import com.rainwen.shiro.vo.UrlPermissionVO;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

import static com.rainwen.shiro.constant.Constants.SUPER_PARENT_ID;

/**
 * @author rain.wen
 * @date 2017/8/9
 */
@Service
@Transactional(rollbackFor = RuntimeException.class)
public class SysResourceService {

    private final static Logger logger = LoggerFactory.getLogger(SysResourceService.class);

    @Autowired
    private SysResourceMapper sysResourceMapper;

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private SysRoleResourceMapper sysRoleResourceMapper;

    public SysResource addSysResource(SysResource sysResource) {
        sysResourceMapper.insertSelective(sysResource);
        return sysResource;
    }

    public int deleteById(Integer id) {
        return sysResourceMapper.deleteByPrimaryKey(id);
    }


    /**
     * 获取登录用户的菜单权限
     *
     * @param userId
     * @return
     */
    @Transactional(readOnly = true, rollbackFor = Exception.class)
    public ResourcePermissionVO findMenuResourceByUserId(Integer userId) {
        long begin = System.currentTimeMillis();
        try {
            List<Integer> roleIds = sysUserService.findRoleIds(userId);
            Set<Integer> resourceIds = findResourceIds(roleIds);
            List<SysResource> sysResourceList = sysResourceMapper.findResourcesByIds(StringUtils.join(resourceIds, ","));

            return constructResourcePermissionVO(sysResourceList);
        } finally {
            logger.info("加载菜单权限耗时:{}", System.currentTimeMillis() - begin);
        }

    }

    private ResourcePermissionVO constructResourcePermissionVO(List<SysResource> sysResourceList) {
        Map<Integer, ResourceVO> resourceVOMap = new LinkedHashMap<Integer, ResourceVO>(sysResourceList.size());
        Map<String, String> urlPermissionMap = new LinkedHashMap<String, String>(sysResourceList.size());
        for (SysResource sysResource : sysResourceList) {
            List<ResourceVO> childResources = new ArrayList<ResourceVO>();
            ResourceVO resourceVO = new ResourceVO();
            resourceVO.setId(sysResource.getId());
            resourceVO.setName(sysResource.getName());
            resourceVO.setType(sysResource.getType());
            resourceVO.setUrl(sysResource.getUrl());
            resourceVO.setIcon(sysResource.getIcon());
            resourceVO.setChildResources(childResources);
            resourceVO.setParentId(sysResource.getParentId());

            if(StringUtils.isNotEmpty(sysResource.getUrl())) {
                urlPermissionMap.put(sysResource.getUrl(), sysResource.getPermission());
            }

            if(!StringUtils.equals(sysResource.getType(), ResourceEnum.DIR.name()) &&
                    !StringUtils.equals(sysResource.getType(), ResourceEnum.MENU.name())) {
                continue;
            }

            Integer parentId = sysResource.getParentId();
            //顶级节点
            if (parentId == SUPER_PARENT_ID) {
                resourceVOMap.put(sysResource.getId(), resourceVO);
                continue;
            }
            //存在父节点
            if (resourceVOMap.containsKey(parentId)) {
                ResourceVO parentResource = resourceVOMap.get(parentId);
                parentResource.getChildResources().add(resourceVO);
                if(!resourceVOMap.containsKey(sysResource.getId())) {
                    resourceVOMap.put(sysResource.getId(), resourceVO);
                }
            }
        }
        ResourcePermissionVO resourcePermissionVO = new ResourcePermissionVO();
        List<ResourceVO> resourceVOList = new ArrayList<ResourceVO>(resourceVOMap.size());
        resourcePermissionVO.setResourceVOList(resourceVOList);
        resourcePermissionVO.setUrlPermissionMap(urlPermissionMap);

        Iterator<Map.Entry<Integer, ResourceVO>> iterator = resourceVOMap.entrySet().iterator();
        while (iterator.hasNext()) {
            ResourceVO resourceVO = iterator.next().getValue();
            if(resourceVO.getParentId() == SUPER_PARENT_ID) {
                resourceVOList.add(resourceVO);
            }
        }
        return resourcePermissionVO;
    }

    /**
     * 查询角色对应的资源ID
     *
     * @param roleIds
     * @return
     */
    public Set<Integer> findResourceIds(List<Integer> roleIds) {
        return sysRoleResourceMapper.findResourceIds(StringUtils.join(roleIds, ","));
    }

    /**
     * 查询资源权限字符串
     *
     * @param resourceIds
     * @return
     */
    public Set<String> findResourcePermissions(Iterable<Integer> resourceIds) {
        return sysResourceMapper.findResourcePermissions(StringUtils.join(resourceIds, ","));
    }

    /**
     * 查询资源权限对象
     *
     * @param resourceIds
     * @return
     */
    public List<UrlPermissionVO> findUrlPermissions(Iterable<Integer> resourceIds) {
        return sysResourceMapper.findUrlPermissions(StringUtils.join(resourceIds, ","));
    }


}
